package com.hugedata.cdn.util;

import java.lang.reflect.UndeclaredThrowableException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * 
 * 项目名称：cdn 类名称：CdnTransactionTemplate 类描述： 创建人：zhaoaihua 创建时间�?013-3-21
 * 下午5:32:00 修改备注�?
 * 
 * @version
 * 
 */
public class CdnTransactionTemplate extends TransactionTemplate {
    /**
     * 注释内容
     */
    private static final long serialVersionUID = 2868994386374151180L;

    protected final Log       log              = LogFactory.getLog(getClass());

    /**
     * 执行事务
     * 
     * @param action
     *            回调�?
     * @throws MvasException
     *             [参数说明]
     * @return Object [返回类型说明]
     * @see [类�?�?方法、类#成员]
     */
    public Object execute(CdnTransactionCallback action) throws CdnException {

        TransactionStatus status = this.getTransactionManager().getTransaction(
                this);
        Object result = null;
        try {
            result = action.doInTransaction(status);
        } catch (RuntimeException ex) {
            // Transactional code threw application exception -> rollback
            rollbackOnException(status, ex);
            throw ex;
        } catch (CdnException e) {
            // Transactional code threw application exception -> rollback
            rollbackOnException(status, e);
            throw e;
        } catch (Error err) {
            // Transactional code threw error -> rollback
            rollbackOnException(status, err);
        } catch (Exception ex) {
            // Transactional code threw unexpected exception -> rollback
            rollbackOnException(status, ex);
            throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
        }

        log.debug("db transaction commit , db success");

        super.getTransactionManager().commit(status);
        return result;

    }

    /**
     * Perform a rollback, handling rollback exceptions properly.
     * 
     * @param status
     *            object representing the transaction
     * @param ex
     *            the thrown application exception or error
     */
    private void rollbackOnException(TransactionStatus status, Throwable ex) {
        log.error("Initiating transaction rollback on application exception",
                ex);
        try {
            this.getTransactionManager().rollback(status);
        } catch (TransactionSystemException ex2) {
            log.error("Application exception overridden by rollback exception",
                    ex);
            ex2.initApplicationException(ex);
            throw ex2;
        } catch (RuntimeException ex2) {
            log.error("Application exception overridden by rollback exception",
                    ex);
            throw ex2;
        } catch (Error err) {
            log.error("Application exception overridden by rollback error", ex);
            throw err;
        }
    }

}
